Added api to set a window to fullscreen on a given monitor.
authorJeremy Whiting <jpwhiting@kde.org>
Mon, 13 Jul 2015 16:30:42 +0000 (10:30 -0600)
committerJeremy Whiting <jpwhiting@kde.org>
Sat, 25 Jul 2015 13:08:59 +0000 (07:08 -0600)
https://bugzilla.gnome.org/show_bug.cgi?id=752677

gdk/gdkwindow.c
gdk/gdkwindow.h
gdk/gdkwindowimpl.h
gdk/wayland/gdkprivate-wayland.h
gdk/wayland/gdkscreen-wayland.c
gdk/wayland/gdkwindow-wayland.c
gtk/gtkwindow.c
gtk/gtkwindow.h

index f6516e5130d55bbe6c3e284e29f3355924b48d57..18ba8ac8afd324fb287ad1c9ab30c29b84d1933f 100644 (file)
@@ -10297,6 +10297,32 @@ gdk_window_fullscreen (GdkWindow *window)
   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen (window);
 }
 
+/**
+ * gdk_window_fullscreen_on_monitor:
+ * @window: a toplevel #GdkWindow
+ * @monitor: Which monitor to display fullscreen on.
+ *
+ * Moves the window into fullscreen mode on the given monitor. This means
+ * the window covers the entire screen and is above any panels or task bars.
+ *
+ * If the window was already fullscreen, then this function does nothing.
+ * Since: UNRELEASED
+ **/
+void
+gdk_window_fullscreen_on_monitor (GdkWindow      *window,
+                                  gint            monitor)
+{
+  GdkScreen *screen = gdk_window_get_screen (window);
+
+  g_return_if_fail (monitor >= 0);
+  g_return_if_fail (monitor < gdk_screen_get_n_monitors (screen));
+
+  if (GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen_on_monitor != NULL)
+    GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen_on_monitor (window, monitor);
+  else
+    GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen (window);
+}
+
 /**
  * gdk_window_set_fullscreen_mode:
  * @window: a toplevel #GdkWindow
index 98c59b8f35cd3584f62ef65d92d7753922859b90..7eee68464f632c4028f3bedbb10e5430621f1b3b 100644 (file)
@@ -952,6 +952,9 @@ GDK_AVAILABLE_IN_ALL
 void          gdk_window_unmaximize      (GdkWindow       *window);
 GDK_AVAILABLE_IN_ALL
 void          gdk_window_fullscreen      (GdkWindow       *window);
+GDK_AVAILABLE_IN_3_18
+void          gdk_window_fullscreen_on_monitor (GdkWindow      *window,
+                                                gint            monitor);
 GDK_AVAILABLE_IN_3_8
 void          gdk_window_set_fullscreen_mode (GdkWindow   *window,
                                           GdkFullscreenMode mode);
index 73a819a8f23578cc49ac49d73ab773b975122a42..07a307c269a36b48bdf69a7dd35367e8624437b1 100644 (file)
@@ -198,6 +198,7 @@ struct _GdkWindowImplClass
   void         (* maximize)             (GdkWindow *window);
   void         (* unmaximize)           (GdkWindow *window);
   void         (* fullscreen)           (GdkWindow *window);
+  void         (* fullscreen_on_monitor) (GdkWindow *window, gint monitor);
   void         (* apply_fullscreen_mode) (GdkWindow *window);
   void         (* unfullscreen)         (GdkWindow *window);
   void         (* set_keep_above)       (GdkWindow *window,
index cd36c2e4e1030b7d31ae1ab18213f64d13b5df58..5f8f37d12d657ae269d5a90b7240fb98b3541138 100644 (file)
@@ -213,6 +213,8 @@ int _gdk_wayland_screen_get_output_refresh_rate (GdkScreen        *screen,
                                                  struct wl_output *output);
 guint32 _gdk_wayland_screen_get_output_scale (GdkScreen        *screen,
                                              struct wl_output *output);
+struct wl_output *_gdk_wayland_screen_get_wl_output (GdkScreen *screen,
+                                                     gint monitor_num);
 
 void _gdk_wayland_screen_set_has_gtk_shell (GdkScreen       *screen);
 
index a2740871af87b10958917a28963ee6f25a5779bb..b07483bc697ae377d743a4f490fccc63973003cc 100644 (file)
@@ -1143,6 +1143,15 @@ _gdk_wayland_screen_add_output (GdkScreen        *screen,
   wl_output_add_listener (output, &output_listener, monitor);
 }
 
+struct wl_output *
+_gdk_wayland_screen_get_wl_output (GdkScreen *screen,
+                                   gint monitor_num)
+{
+  GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
+  GdkWaylandMonitor *monitor = g_ptr_array_index (screen_wayland->monitors, monitor_num);
+  return monitor->output;
+}
+
 void
 _gdk_wayland_screen_remove_output (GdkScreen *screen,
                                    guint32    id)
index d5880b6e25a736e2d962b44535b2d6927083ba7b..e9d077e00e0c2120db04f045221225d79f9d1b1e 100644 (file)
@@ -141,6 +141,8 @@ struct _GdkWindowImplWayland
   int margin_right;
   int margin_top;
   int margin_bottom;
+  
+  int initial_fullscreen_monitor;
 
   cairo_region_t *opaque_region;
   cairo_region_t *input_region;
@@ -168,6 +170,7 @@ static void
 _gdk_window_impl_wayland_init (GdkWindowImplWayland *impl)
 {
   impl->scale = 1;
+  impl->initial_fullscreen_monitor = -1;
 }
 
 /*
@@ -996,6 +999,10 @@ gdk_wayland_window_create_xdg_surface (GdkWindow *window)
   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
   const gchar *app_id;
+  GdkScreen *screen = gdk_window_get_screen (window);
+  struct wl_output *fullscreen_output = NULL;
+  if (impl->initial_fullscreen_monitor < gdk_screen_get_n_monitors (screen))
+      fullscreen_output = _gdk_wayland_screen_get_wl_output (screen, impl->initial_fullscreen_monitor);
 
   impl->xdg_surface = xdg_shell_get_xdg_surface (display_wayland->xdg_shell, impl->surface);
   xdg_surface_add_listener (impl->xdg_surface, &xdg_surface_listener, window);
@@ -1007,7 +1014,7 @@ gdk_wayland_window_create_xdg_surface (GdkWindow *window)
   if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
     xdg_surface_set_maximized (impl->xdg_surface);
   if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
-    xdg_surface_set_fullscreen (impl->xdg_surface, NULL);
+    xdg_surface_set_fullscreen (impl->xdg_surface, fullscreen_output);
 
   app_id = impl->application.application_id;
   if (app_id == NULL)
@@ -1897,6 +1904,25 @@ gdk_wayland_window_unmaximize (GdkWindow *window)
     gdk_synthesize_window_state (window, GDK_WINDOW_STATE_MAXIMIZED, 0);
 }
 
+static void
+gdk_wayland_window_fullscreen_on_monitor (GdkWindow *window, gint monitor)
+{
+  GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+  GdkScreen *screen = gdk_window_get_screen (window);
+  struct wl_output *fullscreen_output = 
+    _gdk_wayland_screen_get_wl_output (screen, monitor);
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (impl->xdg_surface)
+    xdg_surface_set_fullscreen (impl->xdg_surface, fullscreen_output);
+  else {
+    gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN);
+    impl->initial_fullscreen_monitor = monitor;
+  }
+}
+
 static void
 gdk_wayland_window_fullscreen (GdkWindow *window)
 {
@@ -1905,6 +1931,8 @@ gdk_wayland_window_fullscreen (GdkWindow *window)
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  impl->initial_fullscreen_monitor = -1;
+
   if (impl->xdg_surface)
     xdg_surface_set_fullscreen (impl->xdg_surface, NULL);
   else
@@ -1915,10 +1943,12 @@ static void
 gdk_wayland_window_unfullscreen (GdkWindow *window)
 {
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
-
+  
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  impl->initial_fullscreen_monitor = -1;
+
   if (impl->xdg_surface)
     xdg_surface_unset_fullscreen (impl->xdg_surface);
   else
@@ -2316,6 +2346,7 @@ _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass)
   impl_class->maximize = gdk_wayland_window_maximize;
   impl_class->unmaximize = gdk_wayland_window_unmaximize;
   impl_class->fullscreen = gdk_wayland_window_fullscreen;
+  impl_class->fullscreen_on_monitor = gdk_wayland_window_fullscreen_on_monitor;
   impl_class->unfullscreen = gdk_wayland_window_unfullscreen;
   impl_class->set_keep_above = gdk_wayland_window_set_keep_above;
   impl_class->set_keep_below = gdk_wayland_window_set_keep_below;
index 4b45a0dac6cca47deb49c9a90339aceaa1d08313..0b53cd4f6ad647f01d2c334257ebf73f26dd0e0f 100644 (file)
@@ -187,6 +187,7 @@ struct _GtkWindowPrivate
   GtkWidget *popup_menu;
 
   GdkWindow *border_window[8];
+  gint       initial_fullscreen_monitor;
 
   /* The following flags are initially TRUE (before a window is mapped).
    * They cause us to compute a configure request that involves
@@ -1642,6 +1643,7 @@ gtk_window_init (GtkWindow *window)
   priv->initial_timestamp = GDK_CURRENT_TIME;
   priv->mnemonics_visible = TRUE;
   priv->focus_visible = TRUE;
+  priv->initial_fullscreen_monitor = -1;
 
   g_object_ref_sink (window);
   priv->has_user_ref_count = TRUE;
@@ -6060,6 +6062,7 @@ gtk_window_map (GtkWidget *widget)
   GtkWindowPrivate *priv = window->priv;
   GdkWindow *gdk_window;
   GList *link;
+  GdkScreen *screen;
 
   if (!gtk_widget_is_toplevel (widget))
     {
@@ -6067,6 +6070,10 @@ gtk_window_map (GtkWidget *widget)
       return;
     }
 
+  screen = gtk_window_get_screen (widget);
+  if (priv->initial_fullscreen_monitor > gdk_screen_get_n_monitors (screen))
+    priv->initial_fullscreen_monitor = -1;
+    
   gtk_widget_set_mapped (widget, TRUE);
 
   child = gtk_bin_get_child (&(window->bin));
@@ -6096,7 +6103,13 @@ gtk_window_map (GtkWidget *widget)
     gdk_window_deiconify (gdk_window);
 
   if (priv->fullscreen_initially)
-    gdk_window_fullscreen (gdk_window);
+    {
+      if (priv->initial_fullscreen_monitor < 0)
+        gdk_window_fullscreen (gdk_window);
+      else
+        gdk_window_fullscreen_on_monitor (gdk_window, 
+                                          priv->initial_fullscreen_monitor);
+    }
   else
     gdk_window_unfullscreen (gdk_window);
 
@@ -10161,6 +10174,48 @@ gtk_window_fullscreen (GtkWindow *window)
     gdk_window_fullscreen (toplevel);
 }
 
+/**
+ * gtk_window_fullscreen_on_monitor:
+ * @window: a #GtkWindow
+ * @screen: a #GdkScreen to draw to
+ * @monitor: which monitor to go fullscreen on
+ *
+ * Asks to place @window in the fullscreen state. Note that you shouldn't assume
+ * the window is definitely full screen afterward.
+ *
+ * You can track the fullscreen state via the "window-state-event" signal
+ * on #GtkWidget.
+ *
+ * Since: 3.18
+ */
+void
+gtk_window_fullscreen_on_monitor (GtkWindow *window,
+                                  GdkScreen *screen,
+                                  gint monitor)
+{
+  GtkWindowPrivate *priv;
+  GtkWidget *widget;
+  GdkWindow *toplevel;
+  
+  g_return_if_fail (GTK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_SCREEN (screen));
+  g_return_if_fail (monitor >= 0);
+  g_return_if_fail (monitor < gdk_screen_get_n_monitors (screen));
+  
+  priv = window->priv;
+  widget = GTK_WIDGET (window);
+
+  gtk_window_set_screen (window, screen);
+
+  priv->initial_fullscreen_monitor = monitor;
+  priv->fullscreen_initially = TRUE;
+
+  toplevel = gtk_widget_get_window (widget);
+
+  if (toplevel != NULL)
+    gdk_window_fullscreen_on_monitor (toplevel, monitor);
+}
+
 /**
  * gtk_window_unfullscreen:
  * @window: a #GtkWindow
@@ -10188,6 +10243,8 @@ gtk_window_unfullscreen (GtkWindow *window)
   window->priv->fullscreen_initially = FALSE;
 
   toplevel = gtk_widget_get_window (GTK_WIDGET (window));
+  window->priv->fullscreen_initially = FALSE;
+  window->priv->initial_fullscreen_monitor = -1;
 
   if (toplevel != NULL)
     gdk_window_unfullscreen (toplevel);
@@ -10491,6 +10548,9 @@ gtk_window_set_screen (GtkWindow *window,
   if (screen == priv->screen)
     return;
 
+  /* reset initial_fullscreen_monitor since they are relative to the screen */
+  priv->initial_fullscreen_monitor = -1;
+  
   widget = GTK_WIDGET (window);
 
   previous_screen = priv->screen;
index b40efdc875622eb2e410c09f22792587ad14f152..bd73697f38887083b52ef863421618cf047dee2f 100644 (file)
@@ -387,6 +387,10 @@ GDK_AVAILABLE_IN_ALL
 void     gtk_window_fullscreen    (GtkWindow *window);
 GDK_AVAILABLE_IN_ALL
 void     gtk_window_unfullscreen  (GtkWindow *window);
+GDK_AVAILABLE_IN_3_18
+void     gtk_window_fullscreen_on_monitor(GtkWindow *window,
+                                          GdkScreen *screen,
+                                          gint monitor);
 GDK_AVAILABLE_IN_3_10
 void     gtk_window_close         (GtkWindow *window);
 GDK_AVAILABLE_IN_ALL